#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
语音控制服务

集成实时音频采集、ASR识别和智能指令处理的完整语音控制解决方案
"""

import asyncio
import threading
import time
import json
from typing import Dict, Any, Optional, Callable
from pathlib import Path

# 处理相对导入和直接运行的兼容性
try:
    from .realtime_audio_capture import RealTimeAudioCapture, VoiceActivityDetector
    from .asr_service import MinimalASR
    from .intelligent_command_service import IntelligentCommandService
    from .llm_client import LLMClient
except ImportError:
    from realtime_audio_capture import RealTimeAudioCapture, VoiceActivityDetector
    from asr_service import MinimalASR
    from intelligent_command_service import IntelligentCommandService
    from llm_client import LLMClient


class VoiceControlService:
    """
    语音控制服务
    
    完整的语音控制解决方案，包括：
    1. 实时音频采集和VAD
    2. 语音识别 (ASR)
    3. 自然语言理解和指令执行
    4. 语音反馈 (可扩展TTS)
    """
    
    def __init__(self, 
                 config: Optional[Dict[str, Any]] = None,
                 asr_service: Optional[MinimalASR] = None,
                 command_service: Optional[IntelligentCommandService] = None):
        """
        初始化语音控制服务
        
        Args:
            config: 配置参数
            asr_service: ASR服务实例
            command_service: 智能指令服务实例
        """
        # 默认配置
        self.config = {
            "audio": {
                "sample_rate": 16000,
                "channels": 1,
                "chunk_size": 1024,
                "temp_dir": "./temp_audio"
            },
            "vad": {
                "volume_threshold": 0.01,
                "silence_duration": 2.0,
                "min_speech_duration": 0.5
            },
            "asr": {
                "use_cache": True,
                "confidence_threshold": 0.5
            },
            "command": {
                "dry_run": False,
                "save_history": True
            }
        }
        
        # 更新配置
        if config:
            self._update_config(self.config, config)
        
        # 初始化服务组件
        self.audio_capture = RealTimeAudioCapture(
            sample_rate=self.config["audio"]["sample_rate"],
            channels=self.config["audio"]["channels"],
            chunk_size=self.config["audio"]["chunk_size"],
            temp_dir=self.config["audio"]["temp_dir"]
        )
        
        self.asr_service = asr_service or MinimalASR()
        self.command_service = command_service or IntelligentCommandService()
        
        # 设置VAD参数
        self.audio_capture.set_vad_parameters(
            volume_threshold=self.config["vad"]["volume_threshold"],
            silence_duration=self.config["vad"]["silence_duration"],
            min_speech_duration=self.config["vad"]["min_speech_duration"]
        )
        
        # 状态管理
        self.is_active = False
        self.is_processing = False
        self.session_stats = {
            "commands_processed": 0,
            "successful_commands": 0,
            "total_speech_time": 0,
            "session_start_time": None
        }
        
        # 回调函数
        self.on_command_result: Optional[Callable] = None
        self.on_speech_detected: Optional[Callable] = None
        self.on_processing_start: Optional[Callable] = None
        self.on_processing_end: Optional[Callable] = None
        
        # 设置音频回调
        self.audio_capture.on_speech_start = self._on_speech_start
        self.audio_capture.on_speech_end = self._on_speech_end
        
        print("🎯 语音控制服务初始化完成")
        self._print_config()
    
    def _update_config(self, base_config: Dict, new_config: Dict):
        """递归更新配置"""
        for key, value in new_config.items():
            if key in base_config and isinstance(base_config[key], dict) and isinstance(value, dict):
                self._update_config(base_config[key], value)
            else:
                base_config[key] = value
    
    def _print_config(self):
        """打印当前配置"""
        print("⚙️ 当前配置:")
        print(f"   音频: {self.config['audio']['sample_rate']}Hz, {self.config['audio']['channels']}声道")
        print(f"   VAD: 音量阈值={self.config['vad']['volume_threshold']}, 静音={self.config['vad']['silence_duration']}s")
        print(f"   ASR: 缓存={'开启' if self.config['asr']['use_cache'] else '关闭'}")
    
    def start_voice_control(self, device_index: Optional[int] = None):
        """
        启动语音控制
        
        Args:
            device_index: 音频设备索引
        """
        if self.is_active:
            print("⚠️ 语音控制已在运行中")
            return
        
        try:
            print("🚀 启动语音控制服务...")
            
            # 重置统计信息
            self.session_stats = {
                "commands_processed": 0,
                "successful_commands": 0,
                "total_speech_time": 0,
                "session_start_time": time.time()
            }
            
            # 启动音频监听
            self.audio_capture.start_listening(device_index)
            self.is_active = True
            
            print("🎤 语音控制已启动！")
            print("💡 使用提示:")
            print("   - 直接说话即可，系统会自动检测语音")
            print("   - 说完后稍等片刻，系统会自动处理")
            print("   - 支持的指令: 播放音乐、写文章、打开应用等")
            print("   - 按 Ctrl+C 退出")
            
            return True
            
        except Exception as e:
            print(f"❌ 启动语音控制失败: {e}")
            self.is_active = False
            return False
    
    def stop_voice_control(self):
        """停止语音控制"""
        if not self.is_active:
            return
        
        print("🔇 正在停止语音控制...")
        
        self.is_active = False
        self.audio_capture.stop_listening()
        
        # 打印会话统计
        self._print_session_stats()
        
        print("👋 语音控制已停止")
    
    def _on_speech_start(self, vad_result: Dict[str, Any]):
        """语音开始回调"""
        if not self.is_active:
            return
        
        print(f"🟢 检测到语音开始 (音量: {vad_result['volume']:.4f})")
        
        if self.on_speech_detected:
            self.on_speech_detected("start", vad_result)
    
    def _on_speech_end(self, vad_result: Dict[str, Any], audio_file: str):
        """语音结束回调"""
        if not self.is_active:
            return
        
        speech_duration = vad_result.get('speech_duration', 0)
        print(f"🔴 语音结束 (时长: {speech_duration:.2f}秒)")
        
        # 更新统计
        self.session_stats["total_speech_time"] += speech_duration
        
        if self.on_speech_detected:
            self.on_speech_detected("end", vad_result)
        
        # 异步处理音频
        threading.Thread(
            target=self._process_audio_async,
            args=(audio_file, vad_result),
            daemon=True
        ).start()
    
    def _process_audio_async(self, audio_file: str, vad_result: Dict[str, Any]):
        """异步处理音频"""
        if self.is_processing:
            print("⚠️ 正在处理中，请稍后...")
            return
        
        self.is_processing = True
        
        try:
            if self.on_processing_start:
                self.on_processing_start(audio_file)
            
            print("🔄 开始处理语音指令...")
            
            # 步骤1: 上传音频 (这里需要集成实际的上传逻辑)
            print("📤 上传音频文件...")
            audio_url = self._upload_audio_file(audio_file)
            
            if not audio_url:
                print("❌ 音频上传失败")
                return
            
            # 步骤2: ASR识别
            print("🎯 进行语音识别...")
            segments = self.asr_service.recognize(
                audio_url, 
                use_cache=self.config["asr"]["use_cache"]
            )
            
            if not segments:
                print("❌ 语音识别失败")
                return
            
            # 获取识别文本
            recognized_text = self.asr_service.get_full_text(segments)
            print(f"🗣️ 识别结果: {recognized_text}")
            
            if not recognized_text.strip():
                print("⚠️ 未识别到有效文本")
                return
            
            # 步骤3: 指令处理
            print("🧠 分析和执行指令...")
            command_result = self.command_service.process_command(
                recognized_text,
                {
                    "dry_run": self.config["command"]["dry_run"],
                    "confidence_threshold": self.config["asr"]["confidence_threshold"],
                    "save_history": self.config["command"]["save_history"]
                }
            )
            
            # 更新统计
            self.session_stats["commands_processed"] += 1
            if command_result.get("success"):
                self.session_stats["successful_commands"] += 1
            
            # 显示结果
            self._display_command_result(recognized_text, command_result)
            
            # 调用用户回调
            if self.on_command_result:
                self.on_command_result(recognized_text, command_result)
            
        except Exception as e:
            print(f"❌ 处理语音指令失败: {e}")
        
        finally:
            self.is_processing = False
            if self.on_processing_end:
                self.on_processing_end()
    
    def _upload_audio_file(self, audio_file: str) -> Optional[str]:
        """
        上传音频文件到TOS
        
        Args:
            audio_file: 本地音频文件路径
            
        Returns:
            上传后的CDN URL
        """
        try:
            import os
            from pathlib import Path
            
            # 导入TOS配置
            try:
                from config.tos_config import TOSConfig
            except ImportError:
                # 如果导入失败，返回本地路径作为fallback
                print("⚠️ 无法导入TOS配置，使用本地路径")
                return f"file://{os.path.abspath(audio_file)}"
            
            print(f"📤 开始上传音频文件到TOS: {audio_file}")
            
            # 检查文件是否存在
            if not os.path.exists(audio_file):
                print(f"❌ 音频文件不存在: {audio_file}")
                return None
            
            # 创建TOS配置和客户端
            tos_config = TOSConfig()
            tos_client = tos_config.create_tos_client()
            
            if not tos_client:
                print("❌ TOS客户端创建失败")
                return None
            
            # 获取文件名并生成对象键
            file_name = os.path.basename(audio_file)
            # 为音频文件添加特殊的文件夹前缀
            audio_folder = "voice_audio"
            object_key = tos_config.get_full_object_key(file_name, audio_folder)
            
            print(f"   上传到: {object_key}")
            
            # 上传文件到TOS
            with open(audio_file, 'rb') as file_data:
                upload_response = tos_client.put_object(
                    bucket=tos_config.bucket_name,
                    key=object_key,
                    content=file_data
                )
            
            # 检查上传结果
            if upload_response.status_code == 200:
                # 生成CDN访问URL
                cdn_url = tos_config.get_cdn_url(object_key)
                print(f"✅ 音频上传成功: {cdn_url}")
                
                # 删除本地临时文件
                try:
                    os.remove(audio_file)
                    print(f"🗑️ 已删除本地临时文件: {audio_file}")
                except:
                    pass  # 删除失败不影响主流程
                
                return cdn_url
            else:
                print(f"❌ 音频上传失败，状态码: {upload_response.status_code}")
                return None
                
        except Exception as e:
            print(f"❌ 上传音频失败: {e}")
            # 发生错误时，返回本地路径作为fallback
            import os
            return f"file://{os.path.abspath(audio_file)}"
    
    def _display_command_result(self, text: str, result: Dict[str, Any]):
        """显示指令处理结果"""
        print("\n" + "="*60)
        print(f"📝 用户指令: {text}")
        print(f"⏱️ 处理时间: {result.get('processing_time', 0):.2f}秒")
        
        if result.get("success"):
            print(f"✅ 执行成功: {result.get('message', '')}")
            
            # 显示解析结果
            if result.get("parsed_command"):
                parsed = result["parsed_command"]
                print(f"🎯 指令类型: {parsed.get('intent')} -> {parsed.get('action')}")
                print(f"🎲 置信度: {parsed.get('confidence', 0):.2f}")
            
            # 显示执行结果
            if result.get("execution_result"):
                exec_result = result["execution_result"]
                if exec_result.get("success"):
                    print(f"⚡ 执行详情: {exec_result.get('message', '')}")
                else:
                    print(f"❌ 执行失败: {exec_result.get('error', '')}")
        else:
            print(f"❌ 处理失败: {result.get('message', '')}")
        
        print("="*60 + "\n")
    
    def _print_session_stats(self):
        """打印会话统计信息"""
        if self.session_stats["session_start_time"]:
            session_duration = time.time() - self.session_stats["session_start_time"]
            
            print("\n📊 会话统计:")
            print(f"   会话时长: {session_duration:.1f}秒")
            print(f"   处理指令: {self.session_stats['commands_processed']} 个")
            print(f"   成功率: {self.session_stats['successful_commands']}/{self.session_stats['commands_processed']}")
            print(f"   语音时长: {self.session_stats['total_speech_time']:.1f}秒")
            
            if self.session_stats["commands_processed"] > 0:
                success_rate = self.session_stats["successful_commands"] / self.session_stats["commands_processed"] * 100
                print(f"   成功率: {success_rate:.1f}%")
    
    def process_text_command(self, text: str) -> Dict[str, Any]:
        """
        直接处理文本指令 (用于测试或API调用)
        
        Args:
            text: 文本指令
            
        Returns:
            处理结果
        """
        print(f"📝 处理文本指令: {text}")
        
        result = self.command_service.process_command(
            text,
            {
                "dry_run": self.config["command"]["dry_run"],
                "confidence_threshold": self.config["asr"]["confidence_threshold"],
                "save_history": self.config["command"]["save_history"]
            }
        )
        
        self._display_command_result(text, result)
        return result
    
    def get_supported_commands(self) -> Dict[str, Any]:
        """获取支持的指令类型"""
        return self.command_service.get_supported_commands()
    
    def get_session_stats(self) -> Dict[str, Any]:
        """获取会话统计信息"""
        stats = self.session_stats.copy()
        if stats["session_start_time"]:
            stats["session_duration"] = time.time() - stats["session_start_time"]
        return stats
    
    def get_audio_stats(self) -> Dict[str, Any]:
        """获取音频统计信息"""
        return self.audio_capture.get_audio_stats()
    
    def get_status(self) -> Dict[str, Any]:
        """获取完整的服务状态"""
        return {
            "is_active": self.is_active,
            "is_processing": self.is_processing,
            "session_stats": self.get_session_stats(),
            "audio_stats": self.get_audio_stats(),
            "config": self.config
        }
    
    def update_vad_settings(self, **kwargs):
        """更新VAD设置"""
        self.audio_capture.set_vad_parameters(**kwargs)
        
        # 更新配置
        for key, value in kwargs.items():
            if key in self.config["vad"]:
                self.config["vad"][key] = value
    
    def cleanup(self):
        """清理资源"""
        self.stop_voice_control()
        self.audio_capture.cleanup_temp_files()
        print("🧹 资源清理完成")


def main():
    """演示和测试函数"""
    print("🧪 语音控制服务测试")
    print("=" * 50)
    
    # 创建语音控制服务
    voice_service = VoiceControlService()
    
    # 设置回调函数
    def on_command_result(text: str, result: Dict[str, Any]):
        print(f"📢 回调: 指令 '{text}' 处理完成，成功: {result.get('success')}")
    
    def on_processing_start(audio_file: str):
        print(f"⏳ 回调: 开始处理音频 {audio_file}")
    
    voice_service.on_command_result = on_command_result
    voice_service.on_processing_start = on_processing_start
    
    print("\n选择测试模式:")
    print("1. 语音控制模式")
    print("2. 文本指令测试")
    print("3. 显示支持的指令")
    
    try:
        choice = input("请输入选择 (1-3): ").strip()
        
        if choice == "1":
            # 语音控制模式
            voice_service.start_voice_control()
            
            try:
                while voice_service.is_active:
                    time.sleep(0.1)
            except KeyboardInterrupt:
                print("\n👋 用户退出")
        
        elif choice == "2":
            # 文本指令测试
            test_commands = [
                "你好，请帮我播放周杰伦的稻香",
                "帮我写一篇关于人工智能的小说",
                "打开文本编辑器",
                "创建一个新文件叫test.txt"
            ]
            
            print("🧪 测试文本指令:")
            for cmd in test_commands:
                print(f"\n--- 测试: {cmd} ---")
                result = voice_service.process_text_command(cmd)
                time.sleep(1)
        
        elif choice == "3":
            # 显示支持的指令
            commands = voice_service.get_supported_commands()
            print("\n📋 支持的指令类型:")
            for cmd_type, info in commands.items():
                print(f"  {cmd_type}: {info['description']}")
                print(f"    动作: {', '.join(info['actions'])}")
                print(f"    参数: {', '.join(info['parameters'])}")
                print()
        
        else:
            print("❌ 无效选择")
    
    except KeyboardInterrupt:
        print("\n👋 测试结束")
    except Exception as e:
        print(f"❌ 测试失败: {e}")
    finally:
        voice_service.cleanup()


if __name__ == "__main__":
    main()
